/*
 * space.h
 *
 *  Created on: Feb 3, 2012
 *      Author: sxzhang
 */

#ifndef SPACE_H_
#define SPACE_H_
#include <vector.h>
#include <exception.h>

//the space expanded by 3 basis
struct Space{
private:
	DIMI dim;
	VECTORD basisX;
	VECTORD basisY;
	VECTORD basisZ;
private:
	bool isSet;

public:
	Space();
	Space(const DIMI& _dim, const VECTORD& _basisX, const VECTORD& _basisY, const VECTORD& _basisZ);
	DIMI getDim() const;

	VECTORD getbasisX() const;
	VECTORD getbasisY() const;
	VECTORD getbasisZ() const;

	void setSpace(DIMI d, VECTORD bX, VECTORD bY, VECTORD bZ);

	__inline__ COORDD getAbsCoord(const COORDI& co) const;
	__inline__ COORDD getAbsCoordWithOffset(const COORDD& b, const COORDD& offset) const;
};

Space::Space(){
	isSet = false;
}

Space::Space(const DIMI& _dim, const VECTORD& _basisX, const VECTORD& _basisY, const VECTORD& _basisZ){
	setSpace(_dim, _basisX, _basisY, _basisZ);
}

__inline__ DIMI Space::getDim() const{
	if(isSet)
		return dim;
	else
		THROW_LOGIC_EXCEPTION("\"space\" is not correctly set!");
}


__inline__ VECTORD Space::getbasisX() const{
	if(isSet)
		return basisX;
	else
		THROW_LOGIC_EXCEPTION("\"space\" is not correctly set!");
}

__inline__ VECTORD Space::getbasisY() const{
	if(isSet)
		return basisY;
	else
		THROW_LOGIC_EXCEPTION("\"space\" is not correctly set!");
}

__inline__ VECTORD Space::getbasisZ() const{
	if(isSet)
		return basisZ;
	else
		THROW_LOGIC_EXCEPTION("\"space\" is not correctly set!");
}

void Space::setSpace(DIMI d, VECTORD bX, VECTORD bY, VECTORD bZ){
	bool isParametersCorrect=( ((d.x>1)==(!bX.isZero()))
			&& ((d.y>1)==(!bY.isZero()))
			&& ((d.z>1)==(!bZ.isZero())) );
	if(!isParametersCorrect){
		THROW_LOGIC_EXCEPTION("incorrect parameters to define a space!");
	}

	dim = d;
	basisX = bX;
	basisY = bY;
	basisZ = bZ;
	isSet = true;
}

__inline__ COORDD Space::getAbsCoord(const COORDI& co) const
{
	//return getbasisX() * 1   + 2 * getbasisY() + 3*getbasisZ();
	 COORDD d= getbasisX()*(double)co.x + getbasisY()* (double)co.y + getbasisZ() * (double)co.z;
	 return d;
}

__inline__ COORDD Space::getAbsCoordWithOffset(const COORDD& b, const COORDD& offset) const
{
	return b + offset;
}
#endif /* SPACE_H_ */
